/*
 * Copyright (C) 2008 Alessandro Sivieri <alessandro.sivieri@chimera-bellerofonte.eu>.
 *
 *  This file is part of Daex.
 *
 *  Daex is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Foobar is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <dvdread/dvd_reader.h>
#include <dvdread/ifo_types.h>
#include <dvdread/ifo_read.h>
#include <DvdNative.h>

#define EXCEPTION_NAME "eu/chimera_bellerofonte/tesi/datatypes/DvdException"
#define DVDMSG "Impossibile aprire il dvd"
#define IFOMSG "Impossibile leggere l'IFO"
#define DEVMSG "Device non valido (puntatore a null)"

void throw_exception(JNIEnv *env, const char *msg)
{
	jclass cls=(*env)->FindClass(env, EXCEPTION_NAME);
	if(cls!=NULL)
		(*env)->ThrowNew(env, cls, msg);
	(*env)->DeleteLocalRef(env, cls);
}

JNIEXPORT jstring JNICALL Java_eu_chimera_1bellerofonte_tesi_datatypes_DvdNative_getDvdHash
  (JNIEnv * env, jobject obj, jstring dev) {
	const jbyte *s;
	if(dev==NULL)
	{
		throw_exception(env, DEVMSG);
		return NULL;
	}
	s = (*env)->GetStringUTFChars(env, dev, NULL);
	if (s == NULL) {
	    return NULL; /* OutOfMemoryError already thrown */
	}
  	
  	dvd_reader_t * dvd = DVDOpen(s);
  	if(dvd==NULL)
  	{
  		throw_exception(env, DVDMSG);
  		return NULL;
  	}
  	
  	(*env)->ReleaseStringUTFChars(env, dev, s);
  	
  	unsigned char md5sum[16];
  	char buf[3] = "", str[33] = "";
  	int i;
	
	DVDDiscID(dvd, md5sum);
		
	for (i = 0; i < 16; i++) {
		sprintf(buf, "%02x", md5sum[i]);
		strcat(str, buf);	
	}
	
	DVDClose(dvd);
	return (*env)->NewStringUTF(env, str);
  }
  
JNIEXPORT jint JNICALL Java_eu_chimera_1bellerofonte_tesi_datatypes_DvdNative_getDvdTitles
  (JNIEnv * env, jobject obj, jstring dev) {
  	const jbyte *s;
  	if(dev==NULL)
	{
		throw_exception(env, DEVMSG);
		return 0;
	}
	s = (*env)->GetStringUTFChars(env, dev, NULL);
	if (s == NULL) {
	    return 0; /* OutOfMemoryError already thrown */
	}
  	
  	dvd_reader_t * dvd = DVDOpen(s);
  	if(dvd==NULL)
  	{
  		throw_exception(env, DVDMSG);
  		return 0;
  	}
  	
  	(*env)->ReleaseStringUTFChars(env, dev, s);
	
	ifo_handle_t * ifo = ifoOpen(dvd, 0);
	if(ifo==NULL)
	{
		throw_exception(env, IFOMSG);
		DVDClose(dvd);
		return 0;
	}
	int titles = ifo->tt_srpt->nr_of_srpts;
	
	ifoClose(ifo);
	DVDClose(dvd);
	
	return titles;
  }

JNIEXPORT jint JNICALL Java_eu_chimera_1bellerofonte_tesi_datatypes_DvdNative_getDvdMainTitle
  (JNIEnv * env, jobject obj, jstring dev) {
  	const jbyte *s;
  	if(dev==NULL)
	{
		throw_exception(env, DEVMSG);
		return 0;
	}
	s = (*env)->GetStringUTFChars(env, dev, NULL);
	if (s == NULL) {
	    return 0; /* OutOfMemoryError already thrown */
	}
  	
  	dvd_reader_t * dvd = DVDOpen(s);
  	if(dvd==NULL)
  	{
  		throw_exception(env, DVDMSG);
  		return 0;
  	}
  	
  	(*env)->ReleaseStringUTFChars(env, dev, s);
  	
  	int maxtime = 0;
	int maxtimetitle=0;
	
	ifo_handle_t * ifoz = ifoOpen(dvd, 0);
	if(ifoz==NULL)
	{
		throw_exception(env, IFOMSG);
		DVDClose(dvd);
		return 0;
	}
	int titles = ifoz->tt_srpt->nr_of_srpts;
	title_info_t **t = &ifoz->tt_srpt->title;

	int i, temp;
	ifo_handle_t *ifo = ifoOpen(dvd, (*t)->title_set_nr);
	if(ifo==NULL)
	{
		throw_exception(env, IFOMSG);
		DVDClose(dvd);
		return 0;
	}
	pgci_srp_t **p = &ifo->vts_pgcit->pgci_srp;
	temp = (*t)->title_set_nr;
	
	for (i = 1; i <= titles; i++ ) {
		if ((*t)->title_set_nr != temp) {
			//ifoClose(ifo);
			ifo = ifoOpen(dvd, (*t)->title_set_nr);
			if(ifo==NULL)
			{
				throw_exception(env, IFOMSG);
				DVDClose(dvd);
				return 0;
			}
			p = &ifo->vts_pgcit->pgci_srp;
		}
					
		int h = (*p)->pgc->playback_time.hour;
		h = ((h & 0xf0) >> 4) * 10 + (h & 0x0f);
		int m = (*p)->pgc->playback_time.minute;
		m = ((m & 0xf0) >> 4) * 10 + (m & 0x0f);
		int s = (*p)->pgc->playback_time.second;
		s = ((s & 0xf0) >> 4) * 10 + (s & 0x0f);
		
		long time = h * 3600 + m * 60 + s;
		
		if (time > maxtime) {
			maxtime = time;
			maxtimetitle = i;
		}
		
		temp = (*t)->title_set_nr;
		(*t)++;
		(*p)++;
	}
	
	//ifoClose(ifoz);
	DVDClose(dvd);
	
	return maxtimetitle;
  }

JNIEXPORT jint JNICALL Java_eu_chimera_1bellerofonte_tesi_datatypes_DvdNative_getDvdTitleChapters
  (JNIEnv * env, jobject obj, jstring dev, jint title) {
  	const jbyte *s;
  	if(dev==NULL)
	{
		throw_exception(env, DEVMSG);
		return 0;
	}
	s = (*env)->GetStringUTFChars(env, dev, NULL);
	if (s == NULL) {
	    return 0; /* OutOfMemoryError already thrown */
	}
  	
  	dvd_reader_t *dvd = DVDOpen(s);
  	if(dvd==NULL)
  	{
  		throw_exception(env, DVDMSG);
  		return 0;
  	}
  	
  	(*env)->ReleaseStringUTFChars(env, dev, s);
	
	ifo_handle_t *ifoz = ifoOpen(dvd, 0);
	if(ifoz==NULL)
	{
		throw_exception(env, IFOMSG);
		DVDClose(dvd);
		return 0;
	}
	int titles_vts = ifoz->vts_atrt->nr_of_vtss;
	title_info_t **t = &ifoz->tt_srpt->title;
	int i, j;
	
	for (i = 1; i <= titles_vts; i++) {
		ifo_handle_t *ifo = ifoOpen(dvd, i);
		if(ifo==NULL)
		{
			throw_exception(env, IFOMSG);
			DVDClose(dvd);
			return 0;
		}
		pgci_srp_t **p = &ifo->vts_pgcit->pgci_srp;
		
		int srpts = ifo->vts_pgcit->nr_of_pgci_srp;
		
		for (j = 1; j <= srpts; j++) {
			if ((*t)->title_set_nr == title) {
				DVDClose(dvd);

				return (*p)->pgc->nr_of_programs;
			}

			(*t)++;
			(*p)++;
		}
		
		//ifoClose(ifo);
	}

	return 0;
  }
